local status_ok, galaxyline = pcall(require, 'galaxyline')
if not status_ok then return end

local mode = vim.fn.mode
local lsp = vim.lsp

local section = galaxyline.section
local theme = require('themes.galaxyline')
local dotcolors = theme.colors

--[[/* CONSTANTS */]]

-- Defined in https://github.com/Iron-E/nvim-highlite
local _COLORS = {
    bar = {middle = dotcolors.gray_dark, side = dotcolors.black},
    text = dotcolors.gray_light
}

-- hex color subtable
local _HEX_COLORS = setmetatable({
    bar = setmetatable({},
                       {__index = function(_, key) return _COLORS.bar[key] end})
}, {__index = function(_, key) return dotcolors[key] end})

local _BG = {
    file = _HEX_COLORS.bar.side,
    git = _HEX_COLORS.blue,
    diagnostic = _HEX_COLORS.bar.middle
}

local replace_termcodes = vim.api.nvim_replace_termcodes

local function t(key) return replace_termcodes(key, true, true, true) end

-- stylua: ignore
local _MODES = {
    ['c'] = {'', {dotcolors.red}},
    ['ce'] = {'', {dotcolors.red_dark}},
    ['cv'] = {'EX', {dotcolors.red_light}},
    ['i'] = {'I', {dotcolors.green}},
    ['ic'] = {'IC', {dotcolors.green_light}},
    ['n'] = {'N', {dotcolors.purple_light}},
    ['no'] = {'OP', {dotcolors.purple}},
    ['r'] = {'CR', {dotcolors.cyan}},
    ['r?'] = {':CONFIRM', {dotcolors.cyan}},
    ['rm'] = {'--MORE', {dotcolors.cyan}},
    ['R'] = {'R', {dotcolors.pink}},
    ['Rv'] = {'RV', {dotcolors.pink}},
    ['s'] = {'S', {dotcolors.turqoise}},
    ['S'] = {'S', {dotcolors.turqoise}},
    [t '<C-s>'] = {'S-L', {dotcolors.turqoise}},
    ['t'] = {'T', {dotcolors.orange}},
    ['v'] = {'V', {dotcolors.blue}},
    ['V'] = {'V-L', {dotcolors.blue}},
    [t '<C-v>'] = {'V-B', {dotcolors.blue}},
    ['!'] = {'SHELL', {dotcolors.yellow}},

    -- libmodal
    ['TABS'] = {dotcolors.tan},
    ['BUFFERS'] = {dotcolors.teal},
    ['TABLES'] = {dotcolors.orange_light}
}

local _ICONS = {
    Separators = {
        left = '',
        right = '',

        rounded = {left = '', right = ''}
    },
    Git = {add = ' ', delete = ' ', change = ' '},
    Diagnostics = {
        ['error'] = ' ',
        warning = ' ',
        info = ' ',
        hint = ' '
    },
    Lsp = {on = ''}
}

--[[/* PROVIDERS */]]

local function all(...)
    local args = {...}
    return function()
        for _, fn in ipairs(args) do if not fn() then return false end end
        return true
    end
end

local function buffer_not_empty() return vim.fn.empty(vim.fn.expand('%:t')) ~= 1 end

local function checkwidth() return (vim.fn.winwidth(0) / 2) > 40 end

local function find_git_root()
    return
        require('galaxyline/provider_vcs').get_git_dir(vim.fn.expand('%:p:h'))
end

local function get_file_icon_color()
    return require('galaxyline/provider_fileinfo').get_file_icon_color()
end

local function printer(str) return function() return str end end

-- local function negated(fn)
--     return function() return not fn() end
-- end

local function lsp_diagnostic_count(bufnr)
    local cnt = #lsp.diagnostic.get(bufnr)
    return cnt
end

local space = printer(' ')

local lsp_messages = function() return
    require('utils.lsp_status').get_messages() end

local lsp_icon = function()
    if require('utils.lsp_status').get_name() == '' then
        return ''
    else
        return ' ' .. _ICONS.Lsp.on .. ' '
    end
end

--[[/* GALAXYLINE CONFIG */]]

galaxyline.short_line_list = {
    'dbui', 'diff', 'undotree', 'vista', 'man', 'help', 'NvimTree', 'packer'
}

section.left = {
    {
        ViMode = {
            provider = function() -- auto change color according the vim mode
                local current_mode = _MODES[mode(true)] or _MODES[mode(false)]

                local mode_name = current_mode[1]
                local mode_color = current_mode[2]

                require('highlite').highlight('GalaxyViMode',
                                              {fg = mode_color, style = 'bold'})

                return mode_name .. ' '
            end,
            icon = '▊ ',
            highlight = {_HEX_COLORS.bar.side, _HEX_COLORS.bar.side},
            separator = _ICONS.Separators.right,
            separator_highlight = {_HEX_COLORS.black2, get_file_icon_color} -- bar.side != black here, I don't know why
        }
    }, {
        FileIcon = {
            provider = {space, 'FileIcon'},
            highlight = {_HEX_COLORS.bar.side, get_file_icon_color},
            separator = _ICONS.Separators.left,
            separator_highlight = {_BG.file, get_file_icon_color}
        }
    }, {
        LspIcon = {
            provider = lsp_icon,
            highlight = {_HEX_COLORS.green_light, _BG.file}
        }
    }, {
        FileName = {
            provider = {space, 'FileName', 'FileSize'},
            condition = buffer_not_empty,
            highlight = {_HEX_COLORS.text, _BG.file, 'bold'}
        }
    }, {
        GitSeparator = {
            provider = printer(_ICONS.Separators.right),
            condition = find_git_root,
            highlight = {_BG.file, _BG.git}
        }
    }, {
        GitBranch = {
            provider = {space, printer('  '), 'GitBranch', space},
            condition = find_git_root,
            highlight = {_HEX_COLORS.bar.side, _BG.git, 'bold'}
        }
    }, {
        DiffAdd = {
            provider = 'DiffAdd',
            condition = all(checkwidth, find_git_root),
            icon = _ICONS.Git.add,
            highlight = {_HEX_COLORS.Git.Add, _BG.git}
        }
    }, {
        DiffModified = {
            provider = 'DiffModified',
            condition = all(checkwidth, find_git_root),
            icon = _ICONS.Git.change,
            highlight = {_HEX_COLORS.Git.Change, _BG.git}
        }
    }, {
        DiffRemove = {
            provider = 'DiffRemove',
            condition = all(checkwidth, find_git_root),
            icon = _ICONS.Git.delete,
            highlight = {_HEX_COLORS.Git.Delete, _BG.git}
        }
    }, {
        GitRightEnd = {
            provider = printer(_ICONS.Separators.right),
            highlight = {
                find_git_root() and _BG.git or _BG.file, _HEX_COLORS.bar.middle
            }
        }
    }, {
        DiagnosticSpace = {
            provider = function()
                if lsp_diagnostic_count() > 0 then return ' ' end
                return ''
            end,
            highlight = {_BG.diagnostic, _BG.diagnostic}
        }
    }, {
        DiagnosticError = {
            provider = 'DiagnosticError',
            icon = _ICONS.Diagnostics.error,
            highlight = {_HEX_COLORS.LspDiagnosticsSign.Error, _BG.diagnostic}
        }
    }, {
        DiagnosticWarn = {
            provider = 'DiagnosticWarn',
            icon = _ICONS.Diagnostics.warning,
            highlight = {_HEX_COLORS.LspDiagnosticsSign.Warning, _BG.diagnostic}
        }
    }, {
        DiagnosticInfo = {
            provider = 'DiagnosticInfo',
            icon = _ICONS.Diagnostics.info,
            highlight = {_HEX_COLORS.LspDiagnosticsSign.Info, _BG.diagnostic}
        }
    }, {
        DiagnosticHint = {
            provider = 'DiagnosticHint',
            icon = _ICONS.Diagnostics.hint,
            highlight = {_HEX_COLORS.LspDiagnosticsSign.Hint, _BG.diagnostic}
        }
    }
} -- section.left

section.right = {
    {
        LspMessages = {
            provider = {lsp_messages},
            highlight = {_HEX_COLORS.text, _HEX_COLORS.bar.middle}
        }
    }, {
        RightBegin = {
            provider = space,
            highlight = {_HEX_COLORS.bar.middle, _HEX_COLORS.bar.side},
            separator = _ICONS.Separators.left,
            separator_highlight = {_HEX_COLORS.bar.side, _HEX_COLORS.bar.middle}
        }
    }, {
        FileFormat = {
            provider = {'FileFormat', space},
            highlight = {_HEX_COLORS.text, _HEX_COLORS.bar.side}
        }
    }, {
        FileType = {
            provider = 'FileTypeName',
            highlight = {_HEX_COLORS.black, get_file_icon_color, 'bold'},
            separator = _ICONS.Separators.left,
            separator_highlight = {get_file_icon_color, _HEX_COLORS.bar.side}
        }
    }, {
        FileSep = {
            provider = printer(_ICONS.Separators.right),
            highlight = {get_file_icon_color, _HEX_COLORS.bar.side}
        }
    }, {
        LineNumber = {
            provider = function() return vim.fn.line('.') end,
            icon = ' ',
            condition = buffer_not_empty,
            highlight = {_HEX_COLORS.text, _HEX_COLORS.bar.side},
            separator = ' ',
            separator_highlight = {_HEX_COLORS.bar.side, _HEX_COLORS.bar.side}
        },
        ColumnNumber = {
            provider = function() return vim.fn.col('.') end,
            icon = ' ',
            condition = buffer_not_empty,
            highlight = {_HEX_COLORS.text, _HEX_COLORS.bar.side},
            separator = ' ',
            separator_highlight = {_HEX_COLORS.bar.side, _HEX_COLORS.bar.side}
        },

        WhiteSpace = {
            provider = {space, space, 'WhiteSpace'}, -- why one more space is required?
            condition = function()
                return require('galaxyline.provider_whitespace').get_item() ~=
                           ''
            end,
            highlight = {_HEX_COLORS.yellow, _HEX_COLORS.bar.side}
        }
    }, {
        PerCentSeparator = {
            provider = printer(_ICONS.Separators.left),
            highlight = {_HEX_COLORS.magenta_dark, _HEX_COLORS.bar.side},
            separator = ' ',
            separator_highlight = {_HEX_COLORS.bar.side, _HEX_COLORS.bar.side}
        }
    }, {
        PerCent = {
            provider = 'LinePercent',
            highlight = {_HEX_COLORS.white, _HEX_COLORS.magenta_dark}
        }
    }
} -- section.right

section.short_line_left = {
    {
        BufferType = {
            provider = {space, space, 'FileTypeName', space},
            highlight = {_HEX_COLORS.black, _HEX_COLORS.purple, 'bold'},
            separator = _ICONS.Separators.right,
            separator_highlight = {_HEX_COLORS.purple, _HEX_COLORS.bar.middle}
        }
    }
}

section.short_line_right = {
    {
        BufferIcon = {
            provider = 'BufferIcon',
            highlight = {_HEX_COLORS.black, _HEX_COLORS.purple, 'bold'},
            separator = _ICONS.Separators.left,
            separator_highlight = {_HEX_COLORS.purple, _HEX_COLORS.bar.middle}
        }
    }
}

-- local gl = require('galaxyline')
-- local colors = require('galaxyline.theme').default
-- local condition = require('galaxyline.condition')
-- local gls = gl.section
-- gl.short_line_list = {'NvimTree', 'vista', 'dbui', 'packer'}

-- gls.left[1] = {
--     RainbowRed = {
--         provider = function() return '▊ ' end,
--         highlight = {colors.blue, colors.bg}
--     }
-- }
-- gls.left[2] = {
--     ViMode = {
--         provider = function()
--             -- auto change color according the vim mode
--             local mode_color = {
--                 n = colors.red,
--                 i = colors.green,
--                 v = colors.blue,
--                 [''] = colors.blue,
--                 V = colors.blue,
--                 c = colors.magenta,
--                 no = colors.red,
--                 s = colors.orange,
--                 S = colors.orange,
--                 [''] = colors.orange,
--                 ic = colors.yellow,
--                 R = colors.violet,
--                 Rv = colors.violet,
--                 cv = colors.red,
--                 ce = colors.red,
--                 r = colors.cyan,
--                 rm = colors.cyan,
--                 ['r?'] = colors.cyan,
--                 ['!'] = colors.red,
--                 t = colors.red
--             }
--             vim.api.nvim_command('hi GalaxyViMode guifg=' ..
--                                      mode_color[vim.fn.mode()] .. ' guibg=' ..
--                                      colors.bg)
--             return '  '
--         end
--     }
-- }
-- gls.left[3] = {
--     FileSize = {
--         provider = 'FileSize',
--         condition = condition.buffer_not_empty,
--         highlight = {colors.fg, colors.bg}
--     }
-- }
-- gls.left[4] = {
--     FileIcon = {
--         provider = 'FileIcon',
--         condition = condition.buffer_not_empty,
--         highlight = {
--             require('galaxyline.provider_fileinfo').get_file_icon_color,
--             colors.bg
--         }
--     }
-- }

-- gls.left[5] = {
--     FileName = {
--         provider = 'FileName',
--         condition = condition.buffer_not_empty,
--         highlight = {colors.fg, colors.bg, 'bold'}
--     }
-- }

-- gls.left[6] = {
--     LineInfo = {
--         provider = 'LineColumn',
--         separator = ' ',
--         separator_highlight = {'NONE', colors.bg},
--         highlight = {colors.fg, colors.bg}
--     }
-- }

-- gls.left[7] = {
--     PerCent = {
--         provider = 'LinePercent',
--         separator = ' ',
--         separator_highlight = {'NONE', colors.bg},
--         highlight = {colors.fg, colors.bg, 'bold'}
--     }
-- }

-- gls.left[8] = {
--     DiagnosticError = {
--         provider = 'DiagnosticError',
--         icon = '  ',
--         highlight = {colors.red, colors.bg}
--     }
-- }
-- gls.left[9] = {
--     DiagnosticWarn = {
--         provider = 'DiagnosticWarn',
--         icon = '  ',
--         highlight = {colors.yellow, colors.bg}
--     }
-- }

-- gls.left[10] = {
--     DiagnosticHint = {
--         provider = 'DiagnosticHint',
--         icon = '  ',
--         highlight = {colors.cyan, colors.bg}
--     }
-- }

-- gls.left[11] = {
--     DiagnosticInfo = {
--         provider = 'DiagnosticInfo',
--         icon = '  ',
--         highlight = {colors.blue, colors.bg}
--     }
-- }

-- gls.mid[1] = {
--     ShowLspClient = {
--         provider = 'GetLspClient',
--         condition = function()
--             local tbl = {['dashboard'] = true, [''] = true}
--             if tbl[vim.bo.filetype] then return false end
--             return true
--         end,
--         icon = ' LSP:',
--         highlight = {colors.yellow, colors.bg, 'bold'}
--     }
-- }

-- gls.right[1] = {
--     FileEncode = {
--         provider = 'FileEncode',
--         condition = condition.hide_in_width,
--         separator = ' ',
--         separator_highlight = {'NONE', colors.bg},
--         highlight = {colors.green, colors.bg, 'bold'}
--     }
-- }

-- gls.right[2] = {
--     FileFormat = {
--         provider = 'FileFormat',
--         condition = condition.hide_in_width,
--         separator = ' ',
--         separator_highlight = {'NONE', colors.bg},
--         highlight = {colors.green, colors.bg, 'bold'}
--     }
-- }

-- gls.right[3] = {
--     GitIcon = {
--         provider = function() return '  ' end,
--         condition = condition.check_git_workspace,
--         separator = ' ',
--         separator_highlight = {'NONE', colors.bg},
--         highlight = {colors.violet, colors.bg, 'bold'}
--     }
-- }

-- gls.right[4] = {
--     GitBranch = {
--         provider = 'GitBranch',
--         condition = condition.check_git_workspace,
--         highlight = {colors.violet, colors.bg, 'bold'}
--     }
-- }

-- gls.right[5] = {
--     DiffAdd = {
--         provider = 'DiffAdd',
--         condition = condition.hide_in_width,
--         icon = '  ',
--         highlight = {colors.green, colors.bg}
--     }
-- }
-- gls.right[6] = {
--     DiffModified = {
--         provider = 'DiffModified',
--         condition = condition.hide_in_width,
--         icon = ' 柳',
--         highlight = {colors.orange, colors.bg}
--     }
-- }
-- gls.right[7] = {
--     DiffRemove = {
--         provider = 'DiffRemove',
--         condition = condition.hide_in_width,
--         icon = '  ',
--         highlight = {colors.red, colors.bg}
--     }
-- }

-- gls.right[8] = {
--     RainbowBlue = {
--         provider = function() return ' ▊' end,
--         highlight = {colors.blue, colors.bg}
--     }
-- }

-- gls.short_line_left[1] = {
--     BufferType = {
--         provider = 'FileTypeName',
--         separator = ' ',
--         separator_highlight = {'NONE', colors.bg},
--         highlight = {colors.blue, colors.bg, 'bold'}
--     }
-- }

-- gls.short_line_left[2] = {
--     SFileName = {
--         provider = 'SFileName',
--         condition = condition.buffer_not_empty,
--         highlight = {colors.fg, colors.bg, 'bold'}
--     }
-- }

-- gls.short_line_right[1] = {
--     BufferIcon = {provider = 'BufferIcon', highlight = {colors.fg, colors.bg}}
-- }
